# -*- coding = utf-8 -*-
# @Time : 2022/1/17 15:44
# @Author : GHHHHHHHHH
# @File : edgeConnector.py
# @Software : PyCharm
import random

import cv2 as cv
import numpy
from tqdm import tqdm

from json_open_close import save_json


class EdgeConnector(object):
    def __init__(self, _map: numpy.ndarray, xLength: int, yLength: int):
        self.map = _map
        self.xLength = xLength
        self.yLength = yLength
        self.WHITE = (255, 255, 255)

    def get_dis(self, x1, y1, x2, y2):
        return ((x1 - x2) ** 2 + (y1 - y2) ** 2) ** 0.5

    def getAllPointsLocations(self) -> list[tuple]:
        return [(x, y) for x in range(self.xLength)
                for y in range(self.yLength)
                if tuple(self.map[x][y]) == self.WHITE]

    def get_nearest_nodes(self, x: int, y: int, new_locs: list):
        tem_dis = []
        for loc in new_locs:
            if not loc['visited']:
                tem_dis.append(((x - loc['loc'][0]) ** 2 + (y - loc['loc'][1]) ** 2) ** 0.5)
            else:
                tem_dis.append(1e5)
        _min = min(tem_dis)
        if _min > 200:
            return -1, -1, -1
        else:
            _index1 = tem_dis.index(_min)
            tem_dis[_index1] += 1e5
            _min = min(tem_dis)
            _index2 = tem_dis.index(_min)
            tem_dis[_index2] += 1e5
            _min = min(tem_dis)
            _index3 = tem_dis.index(_min)
            tem_dis[_index3] += 1e5
        return _index1, _index2, _index3

    def startConnect(self):
        locs = self.getAllPointsLocations()
        length = len(locs)
        new_locs = []
        for i in range(length):
            tem = {
                "visited": False,
                "loc": (locs[i][1], locs[i][0]),
                "id": 0,
                "end": False
            }
            new_locs.append(tem)
        start = random.randint(0, length - 1)
        now_id = 0
        new_locs[start]['id'] = now_id
        new_locs[start]['visited'] = True
        计数器 = 0
        dises = []
        dis = 0
        painted_pointss = []
        painted_points = []
        for i in tqdm(range(len(new_locs) - 1)):
            now_id += 1
            _index1, _index2, _index3 = self.get_nearest_nodes(new_locs[start]['loc'][0], new_locs[start]['loc'][1],
                                                          new_locs)
            if _index1 == -1:
                # break
                painted_pointss.append(painted_points)
                painted_points = []
                dises.append(dis / 10)
                dis = 0
                计数器 += 1
                new_locs[start]['id'] = now_id
                new_locs[start]['visited'] = True
                new_locs[start]['end'] = True
                count = 0
                for loc in new_locs:
                    if not loc['visited']:
                        start = count
                        break
                    count += 1
            else:
                _grad1 = (new_locs[start]['loc'][0] - new_locs[_index1]['loc'][0]) / (
                        new_locs[start]['loc'][1] - new_locs[_index1]['loc'][1] + 1e-6)
                _grad2 = (new_locs[start]['loc'][0] - new_locs[_index2]['loc'][0]) / (
                        new_locs[start]['loc'][1] - new_locs[_index2]['loc'][1] + 1e-6)
                _grad3 = (new_locs[start]['loc'][0] - new_locs[_index3]['loc'][0]) / (
                        new_locs[start]['loc'][1] - new_locs[_index3]['loc'][1] + 1e-6)
                dis1 = (new_locs[start]['loc'][0] - new_locs[_index1]['loc'][0]) ** 2 + (
                        new_locs[start]['loc'][1] - new_locs[_index1]['loc'][1]) ** 2
                dis2 = (new_locs[start]['loc'][0] - new_locs[_index2]['loc'][0]) ** 2 + (
                        new_locs[start]['loc'][1] - new_locs[_index2]['loc'][1]) ** 2
                dis3 = (new_locs[start]['loc'][0] - new_locs[_index3]['loc'][0]) ** 2 + (
                        new_locs[start]['loc'][1] - new_locs[_index3]['loc'][1]) ** 2
                _grad1, _grad2, _grad3 = abs(_grad1), abs(_grad2), abs(_grad3)
                score1 = dis1 * 0.9
                score2 = dis2 * 0.9
                score3 = dis3 * 0.9
                scores = (score1, score2, score3)
                _min = min(scores)
                _index = scores.index(_min)
                if _index == 0:
                    dis += self.get_dis(new_locs[start]['loc'][0], new_locs[start]['loc'][1],
                                   new_locs[_index1]['loc'][0], new_locs[_index1]['loc'][1])
                    painted_points.append(tuple([new_locs[_index1]['loc'][0], new_locs[_index1]['loc'][1]]))
                    start = _index1
                elif _index == 1:
                    dis += self.get_dis(new_locs[start]['loc'][0], new_locs[start]['loc'][1],
                                   new_locs[_index2]['loc'][0], new_locs[_index2]['loc'][1])
                    painted_points.append(tuple([new_locs[_index2]['loc'][0], new_locs[_index2]['loc'][1]]))
                    start = _index2
                else:
                    dis += self.get_dis(new_locs[start]['loc'][0], new_locs[start]['loc'][1],
                                   new_locs[_index3]['loc'][0], new_locs[_index3]['loc'][1])
                    painted_points.append(tuple([new_locs[_index3]['loc'][0], new_locs[_index3]['loc'][1]]))
                    start = _index3
                new_locs[start]['id'] = now_id
                new_locs[start]['visited'] = True
        new_locs.sort(key=lambda new_locs: new_locs["id"])
        for i in tqdm(range(len(new_locs))):
            if new_locs[i]['end']:
                continue
            if i != len(new_locs) - 1:
                if not self.judge_get_distance(new_locs[i]['loc'][0], new_locs[i]['loc'][1], new_locs[i + 1]['loc'][0],
                                          new_locs[i + 1]['loc'][1]):
                    cv.line(self.map, new_locs[i]['loc'], new_locs[i + 1]['loc'], (255, 255, 255), 1)
        for i in range(self.xLength):
            for j in range(self.yLength):
                if tuple(self.map[i][j])[0] > 200 and tuple(self.map[i][j])[1] > 200 and tuple(self.map[i][j])[2] > 200:
                    self.map[i][j] = (255, 255, 255)
                elif tuple(self.map[i][j])[0] < 50 and tuple(self.map[i][j])[1] < 50 and tuple(self.map[i][j])[2] < 50:
                    self.map[i][j] = (0, 0, 0)
        cv.imwrite("result1.jpg", self.map)

    def judge_get_distance(self, x1, y1, x2, y2):
        dis = ((x2 - x1) ** 2 + (y2 - y1) ** 2) ** 0.5
        if dis > 10:
            return True
        return False



